package com.sky.aspect;

import com.sky.anno.Tablelnject;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDate;
import java.time.LocalDateTime;

@Component
@Aspect
@Slf4j
public class TableInjectAspect {
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.anno.Tablelnject)")
    public void pt(){}
    @Before("pt()")
    public void before(JoinPoint jp) {

        MethodSignature signature = (MethodSignature) jp.getSignature();
        Method method = signature.getMethod();

        Object[] params = jp.getArgs();
        if(params == null || params.length == 0 || params.length > 1){
            return;
        }

        Object param = params[0];
        Tablelnject annotation = method.getAnnotation(Tablelnject.class);
        Long currentId = BaseContext.getCurrentId();
        LocalDateTime now = LocalDateTime.now();

        try {
            Method createTimeMethod = param.getClass().getMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
            Method updateTimeMethod = param.getClass().getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method createUserMethod = param.getClass().getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
            Method updateUserMethod = param.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

            switch (annotation.value()) {
                case INSERT:
                    createTimeMethod.invoke(param, now);
                    updateTimeMethod.invoke(param, now);
                    createUserMethod.invoke(param, currentId);
                    updateUserMethod.invoke(param, currentId);
                    break;
                case UPDATE:
                    updateTimeMethod.invoke(param, now);
                    updateUserMethod.invoke(param, currentId);
                    break;
            }
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
}
